﻿using Flurl.Http;
using NPOI.SS.Formula.Functions;
using Pay.Core;
using Pay.DTO;
using Pay.DTO.cjpay;
using Pay.IService;
using Pay.Service.Pay;
using Pay.TO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Pay.Service
{
    public class CjPayService : ServiceBase2, IPayService, IDisposable
    {
        private const string reg_url = "/open/certify/register";
        private const string merchant_reg_url = "/open/cj/register";
        private const string sms_url = "/open/cj/merchantSignSms";
        private const string card_bind_url = "/open/cj/merchantSign";
        private const string card_unbind_url = "/open/pay/unsignbankcard";
        private const string pay_url = "/open/pay/transaction";
        private IMerchantService _iMerchantService;
        private IChargeService _iChargeService;
        private IPayHtmlService _iPayHtmlService;
        private CjPaySign _cjPay;

        public CjPayService(IUnitOfWork unitOfWork, IMerchantService merchantService,
            IChargeService chargeService, CjPaySign cjPay, IPayHtmlService payHtmlService)
            : base(unitOfWork)
        {
            _iMerchantService = merchantService;
            _iChargeService = chargeService;
            _iPayHtmlService = payHtmlService;
            _cjPay = cjPay;
        }

        public Task<transfer_result> AgencyFund(apply_receive model)
        {
            throw new NotImplementedException();
        }

        public async Task<certify_verify_result> CertifyVerify(certify_verify model)
        {
            var card4 = await _cjPay.CertifyVerify(model);
            if (card4 == null)
            {
                return ApiResultToJson.Json("认证失败", new certify_verify_result { status = AuthStatusEnum.Wait });
            }
            if (card4.code == "10000")
            {
                model.status = CertifyStatus.Auth;
                _iMerchantService.CertifyVerify(model, card4.message);
                return ApiResultToJson.Json("认证成功", new certify_verify_result { status = AuthStatusEnum.Auth });
            }
            else
            {
                model.status = CertifyStatus.Fail;
                _iMerchantService.CertifyVerify(model, card4.message);
                return ApiResultToJson.Json(card4.message, new certify_verify_result { status = AuthStatusEnum.Fail });
            }
        }

        public int DealItp(long id)
        {
            throw new NotImplementedException();
        }

        public Task<gateway_pay_result> GatewayPay(gateway_pay_model model)
        {
            throw new NotImplementedException();
        }

        public List<type_setting> GatewayPayBank()
        {
            throw new NotImplementedException();
        }

        public Task<pay_notity> GatewayPayQuery(refund_model_query model)
        {
            throw new NotImplementedException();
        }

        public Task<refund_result> GatewayPayRefund(refund_model model)
        {
            throw new NotImplementedException();
        }

        public Task<refund_result> GatewayRefundQuery(refund_model_query model)
        {
            throw new NotImplementedException();
        }

        public Task<ApiResultMessage> InsteadReceive(verify_model model)
        {
            throw new NotImplementedException();
        }

        public Task<ApiResultMessage> InsteadReceive(verify_model_sms model)
        {
            throw new NotImplementedException();
        }

        public Task<int> ItpToFile(DateTime create_date)
        {
            throw new NotImplementedException();
        }

        public Task<mall_result> MallPay(mall_model obj)
        {
            throw new NotImplementedException();
        }

        public Task<merchant_register_result> MerchantModify(long bind_id, string settle_type, PayChannel channel = PayChannel.None)
        {
            throw new NotImplementedException();
        }

        public async Task<merchant_register_result> MerchantRegister(merchant_register_model dto, string opt)
        {
            var user = _iMerchantService.GetMerchant(dto.bind_no);
            var pay_reg = new cj_pay_reg_req
            {
                merchant_no = user.CjMerchantNo,//注册畅捷商户号
                pay_channel = "cj",
                account_name = dto.account_name,
                id_card = dto.id_card,
                account_no = dto.account_no,
                card_type = 1,
                branch_code = user.BranchCode,//银行编码
                mobile = dto.mobile,
                company_type = 2,
                debit_rate = "0.006",
                credit_rate = "0.006",
                widthdraw_deposit_rate = "0",
                withdraw_deposit_single_fee = "100",
                trans_charge = "100",
                repayment_rate = dto.fee.ToString(),
                repayment_charge = dto.settle
            };
            var log = IocHelper.Get<ILogHelper>("info");
            if (string.IsNullOrEmpty(user.CjMerchantNo))
            {
                log.Info("获取畅捷商户号失败");
                return ApiResultToJson.Json<merchant_register_result>("畅捷商户号，进件失败");
            }
            if (string.IsNullOrEmpty(user.BranchCode))
            {
                return ApiResultToJson.Json<merchant_register_result>("银行编号，进件失败");
            }
            if (opt == "A")
            {
                var reg_result = await _cjPay.PayGateway<cj_pay_reg_res>(pay_reg, merchant_reg_url);
                if (reg_result != null)
                {
                    dto.reg_merchant_no = reg_result.data.merchant_no;
                    return ApiResultToJson.Json(new merchant_register_result { merchant_no = dto.reg_merchant_no });
                }
            }
            else
            {
                //todo:暂时不支持修改进件数据
                return ApiResultToJson.Json(new merchant_register_result { merchant_no = dto.reg_merchant_no });
            }
            return ApiResultToJson.Json<merchant_register_result>("信息登记异常");
        }

        public Task<merchant_register_result> MerchantRegister(long bind_id, string settle_type, PayChannel channel = PayChannel.None)
        {
            throw new NotImplementedException();
        }

        public Task<native_result> NativePay(native_model obj)
        {
            throw new NotImplementedException();
        }

        public async Task<string> Notify(string merchant_no, string order_no)
        {
            string result = string.Empty;
            charge_dto order = _iChargeService.Get(merchant_no, order_no);
            try
            {
                var data = new pay_notity
                {
                    tran_amount = ((int)(order.order_amount * 100)).ToString(),
                    order_no = order.order_no,
                    transaction_no = order.pay_info.transaction_no,
                    pay_time = order.pay_info.pay_time.HasValue ? order.pay_info.pay_time.Value : order.order_time,
                    status = (order.status == ChargeStatus.Finish ? 1 : 2)
                };
                data.result_msg = (data.status == 1 ? "支付成功" : order.fail);
                if (string.IsNullOrEmpty(order.notify)) return "OK";
                var notify_result = await order.notify.PostJsonAsync(ApiResultToJson.Json(data)).ReceiveJson<ResultMessage<string>>();
                result = notify_result.data;
                var log = IocHelper.Get<ILogHelper>("info");
                log.Info(order.order_no + ":" + notify_result.ToJson());
            }
            catch (Exception ex)
            {
                var log = IocHelper.Get<ILogHelper>("info");
                log.Error("订单通道查询异常:" + order.order_no);
                string message = string.Format("消息类型：{0}\r\n消息内容：{1}\r\n引发异常的方法：{2}\r\n引发异常源：{3}"
                                , ex.GetType().Name, ex.Message, ex.TargetSite, ex.Source + ex.StackTrace);
                log.Error(message);
            }
            return result;
        }

        public Task<string> NotifyTransfer(string merchant_no, string order_no)
        {
            throw new NotImplementedException();
        }
        private string GetBankCode(string code)
        {
            var codes = new Dictionary<string, string> {
                { "BCM","BCOM"},
                { "CGB","GDB"}
            };

            return codes.ContainsKey(code) ? codes[code] : code;
        }
        /// <summary>
        /// 发送验证码动作
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<quick_pay_result> QuickPay(quick_pay_model model)
        {
            var log = IocHelper.Get<ILogHelper>("info");
            var binder = _iMerchantService.Get(model.bind_no);
            var channelRegister = _iMerchantService.GetMerchantChannelRegister(binder.id, model.pay_channel);
            var id = Guid.NewGuid().ToString("N");
            string pay_code = model.pay_code;
            model.settle_type = "T0";
            var binder_payments = _iMerchantService.GetPayments(binder.id);
            var payment = binder_payments.FirstOrDefault(c => c.payment.channel == model.pay_channel);
            var settle = payment.settles.First(c => c.settle_type == model.settle_type && c.code == pay_code);
            if (model.settle_fee / 100M != settle.settle)
                return ApiResultToJson.Json<quick_pay_result>("结算费与商户进件的结算费不同");
            if (model.fee != settle.fee)
                return ApiResultToJson.Json<quick_pay_result>("费率与商户进件的费率不同");
            if (model.pay_fee_amount != (int)Math.Ceiling(decimal.Parse(model.tran_amount) * model.fee))
                return ApiResultToJson.Json<quick_pay_result>("实扣费率金额不正确");
            var merchantRegister = _iMerchantService.GetRegister(model.id_card, model.pay_channel);
            if (merchantRegister != null)
            {
                var authInfo = binder.setting.auth_info;
                var unbind_card_req = new cj_unbind_req
                {
                    merchant_no = channelRegister.merchant_no,
                    pay_channel = "cj",
                    account_no = model.account_no
                };
                var unbind_card_result = await _cjPay.PayGateway<cj_unbind_res>(unbind_card_req, card_unbind_url);
                model.bank_code = GetBankCode(model.bank_code);
                var sms_req = new cj_bank_sms_req
                {
                    merchant_no = merchantRegister.merchant_no,
                    pay_channel = "cj",
                    card_type = 2,
                    account_no = model.account_no,
                    mobile = model.mobile,
                    cvn2 = model.cvv2,
                    expired = model.vaild,
                    bank_abbr = model.bank_code,
                    debit_rate = model.fee.ToString(),
                    credit_rate = model.fee.ToString(),
                    withdraw_deposit_rate = "0",
                    withdraw_deposit_single_fee = model.settle_fee.ToString(),
                    trans_charge = "100",
                    repayment_charge = model.settle_fee.ToString(),
                    repayment_rate = model.fee.ToString()
                };

                var sms_result = await _cjPay.PayGateway<cj_bank_sms_res>(sms_req, sms_url);
                if (sms_result != null && sms_result.result_code == 1000)
                {
                    var charge = _iChargeService.AddByQuickPay(model);
                    var ok = _iPayHtmlService.Save(new pay_html_dto
                    {
                        id = id,
                        merchant_no = model.merchant_no,
                        order_no = model.order_no,
                        charge = charge.ToJson()
                    });
                    return ApiResultToJson.Json("鉴权成功，待确认支付", new quick_pay_result
                    {
                        order_no = model.order_no,
                        protocol_no = "",
                        pay_time = DateTime.Now,
                        transaction_no = "",
                        status = 3
                    });
                }
            }
            return ApiResultToJson.Json<quick_pay_result>("异常支付");
        }
        /// <summary>
        /// 确认支付动作
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<quick_pay_result> QuickPay(quick_sms_model model)
        {
            var payHtml = _iPayHtmlService.Get(model.merchant_no, model.order_no);
            var charge = payHtml.charge.ToObject<charge_dto>();
            var binder = _iMerchantService.Get(model.bind_no);
            var channelRegister = _iMerchantService.GetMerchantChannelRegister(binder.id, model.pay_channel);
            var authInfo = binder.setting.auth_info;
            var merchantRegister = _iMerchantService.GetRegister(authInfo.id_card, model.pay_channel);
            //绑卡
            var bind_card_req = new cj_bind_card_req
            {
                merchant_no = merchantRegister.merchant_no,
                pay_channel = "cj",
                card_type = 2,
                account_no = charge.account_no,
                mobile = charge.mobile,
                cvn2 = charge.cvv2,
                expired = charge.vaild,
                sms_code = model.sms_code,
                bank_abbr = charge.bank_code,
                is_need_sms = 1,
                debit_rate = charge.fee.ToString(),
                credit_rate = charge.fee.ToString(),
                withdraw_deposit_rate = "0",
                widthdraw_deposit_single_fee = (charge.settle_fee * 100).ToString(),
                trans_charge = "100",
                repayment_charge = "100",
                repayment_rate = charge.fee.ToString()
            };
            var bind_card_result = await _cjPay.PayGateway<cj_bind_card_res>(bind_card_req, card_bind_url);
            if (bind_card_result != null && bind_card_result.data.result_code == "1000")
            {
                //绑卡成功，进行支付
                var pay_req = new cj_pay_req
                {
                    pay_channel = "cj",
                    merchant_no = channelRegister.merchant_no,
                    trans_amount = (charge.pay_amount * 100).ToString(),
                    trans_type = 1,
                    account_no = charge.account_no,
                    province = authInfo.province,
                    city = authInfo.city,
                    notify_url = "http://pay.timebiz.cn/pay/cj_back_notify/" + payHtml.id,
                    fail_url = "http://pay.timebiz.cn/pay/cj_back_notify/" + payHtml.id
                };
                var pay_result = await _cjPay.PayGateway<cj_pay_res>(pay_req, pay_url);
                if (pay_result != null && pay_result.result_code == 1000)
                {
                    return ApiResultToJson.Json("支付成功", new quick_pay_result { status = 1 });
                }
            }

            return ApiResultToJson.Json<quick_pay_result>("异常支付");
        }

        public Task<pay_notity> QuickPayQuery(refund_model_query model)
        {
            throw new NotImplementedException();
        }

        public Task<refund_result> QuickPayRefund(refund_model model)
        {
            throw new NotImplementedException();
        }

        public Task<refund_result> QuickPayRefundQuery(refund_model_query model)
        {
            throw new NotImplementedException();
        }

        public Task<ApiResultMessage> QuickPaySendsms(quick_sendsms_model model)
        {
            throw new NotImplementedException();
        }

        public Task<quota_result> Quota(string merchant_no, string busiType)
        {
            throw new NotImplementedException();
        }

        public Task<transfer_result> ReTransfer(long id)
        {
            throw new NotImplementedException();
        }

        public Task<transfer_result> TokenTransfer(long id)
        {
            throw new NotImplementedException();
        }

        public Task<transfer_result> TokenTransferQuery(transfer_query model)
        {
            throw new NotImplementedException();
        }

        public Task<transfer_result> Transfer(apply_transfer model)
        {
            throw new NotImplementedException();
        }

        public Task<batch_transfer_result> Transfer(batch_transfer model)
        {
            throw new NotImplementedException();
        }

        public Task<int> TransferBack(long batchId, string noticeTranId, long merchant_id)
        {
            throw new NotImplementedException();
        }

        public Task<int> TransferNotify(long batchId, string batchFileName, long merchant_id)
        {
            throw new NotImplementedException();
        }

        public Task<transfer_result> TransferQuery(transfer_query model)
        {
            throw new NotImplementedException();
        }
    }
}
